﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows.Media;
using Collab.Services.Remote.Entities;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;

namespace Collab.Modules.ViewTracker
{
    public static class HighlightManager
    {
        private static readonly IDictionary<string, List<HighlightAdornment>> activeViews = new Dictionary<string, List<HighlightAdornment>>();
        public static event Action<string, UserSelection> SelectionChanged;


        public static void AddView(IWpfTextView view)
        {
            string fileName = GetFileName(view.TextBuffer);
            Debug.Assert(!string.IsNullOrEmpty(fileName));
            if (activeViews.ContainsKey(fileName))
            {
                activeViews[fileName].Add(new HighlightAdornment(view, selection => SendSelectionChanged(fileName, selection)));
            }
            else
            {
                activeViews[fileName] = new List<HighlightAdornment> { new HighlightAdornment(view, selection => SendSelectionChanged(fileName, selection)) };
            }

        }

        private static void SendSelectionChanged(string fileName, UserSelection selection)
        {
            if (SelectionChanged != null)
            {
                SelectionChanged.Invoke(fileName, selection);
            }
        }

        public static void RemoveView(IWpfTextView view)
        {
            string fileName = GetFileName(view.TextBuffer);
            if (!string.IsNullOrEmpty(fileName) && activeViews.ContainsKey(fileName))
            {
                activeViews[fileName].RemoveAll(adornment => adornment.View == view);
            }
        }

        ///// <summary>
        ///// Returns all the views that are active for a document or null if there are no views
        ///// </summary>
        ///// <param name="filename"></param>
        ///// <returns></returns>
        //public static IList<IWpfTextView> GetViews(string filename)
        //{
        //    return (activeViews.ContainsKey(filename) && activeViews[filename].Count > 0) ? activeViews[filename] : null;
        //}

        public static void Highlight(string filename, UserSelection selection, Tuple<byte, byte, byte> color)
        {
            var col = Color.FromArgb(0x20, color.Item1, color.Item2, color.Item3);
            if (activeViews.ContainsKey(filename) && activeViews[filename].Count > 0)
            {
                ITextBuffer buffer = activeViews[filename].First().View.TextBuffer;
                var adornments = activeViews[filename];
                adornments.ForEach(adornment => adornment.RemoveHighlights(col));

                foreach (var selectedSpan in selection.SelectedSpans)
                {
                    if (buffer.CurrentSnapshot.Length > (selectedSpan.Start + selectedSpan.Length))
                    {
                        var span = buffer.CurrentSnapshot.CreateTrackingSpan(selectedSpan.Start, selectedSpan.Length, SpanTrackingMode.EdgeInclusive);
                        //var span = tSpan.GetSpan(buffer.CurrentSnapshot);
                        adornments.ForEach(adornment => adornment.AddHighlight(span, col));
                    }
                }
                
            }
        }

        public static void RemoveHighlights(string filename, Tuple<byte, byte, byte> color)
        {
            var col = Color.FromArgb(0x20, color.Item1, color.Item2, color.Item3);
            if (activeViews.ContainsKey(filename) && activeViews[filename].Count > 0)
            {
                ITextBuffer buffer = activeViews[filename].First().View.TextBuffer;
                activeViews[filename].ForEach(adornment => adornment.RemoveHighlights(col));
            }
        }


        private static string GetFileName(ITextBuffer buffer)
        {
            Microsoft.VisualStudio.TextManager.Interop.IVsTextBuffer bufferAdapter;
            buffer.Properties.TryGetProperty<Microsoft.VisualStudio.TextManager.Interop.IVsTextBuffer>(typeof(Microsoft.VisualStudio.TextManager.Interop.IVsTextBuffer), out bufferAdapter);
            if (bufferAdapter != null)
            {
                Microsoft.VisualStudio.Shell.Interop.IPersistFileFormat persistFileFormat = bufferAdapter as Microsoft.VisualStudio.Shell.Interop.IPersistFileFormat;
                string ppzsFilename;
                uint iii;
                persistFileFormat.GetCurFile(out ppzsFilename, out iii);
                return ppzsFilename;
            }
            else return null;
        }

    }
}
